﻿using System;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using System.Collections.Generic;
using System.Linq;

namespace Code4WP7SDK
{
    //往前传递消息 - MessageForwardTrain
    public class MorTrain : IMorTrain
    {
        #region Fields
        private static readonly object _creationLock = new object();    //对象创建锁
        private Dictionary<Type, List<SenderInfo>> _dicSenderInfos;     //按照信息类型区分的信息集合
        private readonly object _sendLock = new object();               //发送消息锁
        #endregion

        #region Constructor
        private MorTrain() { }
        private static MorTrain _instance;
        public static MorTrain Instance
        {
            get
            {
                if (_instance == null)
                {
                    lock (_creationLock)
                    {
                        if (_instance == null)
                        {
                            _instance = new MorTrain();
                        }
                    }
                }
                return _instance;
            }
        }
        #endregion

        #region Send
        public void Send<TMessage>(TMessage message)
        {
            SendMessageOrTarget<TMessage>(message, null, null);
        }
        public void Send<TMessage, TTarget>(TMessage message)
        {
            SendMessageOrTarget<TMessage>(message, null,typeof(TTarget));
        }

        public void Send<TMessage>(TMessage message, object token)
        {
            SendMessageOrTarget<TMessage>(message, token, null);
        }

        private void SendMessageOrTarget<TMessage>(TMessage message,object token,Type targetType)
        {
            lock (_sendLock)
            {
                Type messageType = message.GetType();
                Dictionary<Type, List<SenderInfo>> dicSenderInfos;
                if (_dicSenderInfos == null)
                {
                    _dicSenderInfos = new Dictionary<Type, List<SenderInfo>>();
                }
                dicSenderInfos = _dicSenderInfos;
                lock (dicSenderInfos)
                {
                    List<SenderInfo> senderInfos;  //检查是否已经包含了该类型的消息
                    if (!dicSenderInfos.ContainsKey(messageType))
                    {
                        senderInfos = new List<SenderInfo>();
                        dicSenderInfos.Add(messageType, senderInfos);
                    }
                    else
                    {
                        senderInfos = dicSenderInfos[messageType];
                    }
                    SenderInfo senderInfo = new SenderInfo(message, targetType, token);
                    senderInfos.Add(senderInfo);
                }
            }
            //清空不需要的message
        }
        #endregion

        #region Receive
        public void Receive<TMessage>(object taker, Action<TMessage> action)
        {
            Receive<TMessage>(taker, null, action);
        }

        public void Receive<TMessage>(object taker, object token, Action<TMessage> action)
        {
            Type messageType = typeof(TMessage);
            if (_dicSenderInfos != null)
            {
                List<SenderInfo> senderInfos = null;
                List<Type> cloneTypeList = _dicSenderInfos.Keys.Take(_dicSenderInfos.Count).ToList();
                foreach (Type type in cloneTypeList)
                {
                    if (messageType == type) //这个地方要考虑父类的情况
                    {
                        lock (_dicSenderInfos)
                        {
                            senderInfos = _dicSenderInfos[type].Take(_dicSenderInfos[type].Count).ToList();
                        }
                    }
                    ExecuteAction(action, senderInfos,token,taker);
                }
            }
        }
        private void ExecuteAction<TMessage>(Action<TMessage> action, List<SenderInfo> senderInfos,object token,object taker)
        {
            if (senderInfos != null)
            {
                List<SenderInfo> cloneSenderInfos = senderInfos.Take(senderInfos.Count()).ToList();
                foreach (SenderInfo senderInfo in cloneSenderInfos)
                {
                    if (((senderInfo.Token == token && senderInfo.Token != null) || (senderInfo.Token == null && token == null))
                        &&((senderInfo.TargetType == taker.GetType()) || (senderInfo.TargetType == null)))
                    {
                        action((TMessage)senderInfo.Message);
                    }
                }
                CleanSenderInfo(senderInfos);
            }
        }
        #endregion

        #region CleanUp
        public void CleanSenderInfo(List<SenderInfo> senderInfos) 
        {
            foreach (SenderInfo cleanSenderInfo in senderInfos)
            {
                Type messageType = cleanSenderInfo.Message.GetType();
                _dicSenderInfos[messageType].Remove(cleanSenderInfo);   //移除该SenderInfo
                if (_dicSenderInfos[messageType].Count == 0)            //如果该类型的对象为空了则全部移除掉
                {
                    _dicSenderInfos.Remove(messageType);
                }
            }
        }
        #endregion
    }
}
